Skip to content

Conversation

@ysthakur
Copy link
Member

@ysthakur ysthakur commented Jun 9, 2024

Description

This PR adds a match_indices: Option<Vec<usize>> field to the Suggestion struct representing which indices of the Suggestion's value field were matched.

Motivation

Currently, in Nushell, if you have fuzzy matching on, the matches are still highlighted with the assumption that you're using prefix matching:
image

This PR doesn't fix that, but adding match_indices to Suggestion does make it so that completers using fuzzy matching can include the indices of the matches in their returned suggestions. nushell/nushell#15887 will actually fix the issue in Nushell once this PR is merged. Here's the fuzzy_completions example included in this PR, which uses a columnar menu (ignore how bad the fuzzy completion algorithm is, I didn't bother using skim or Nucleo):

asciicast

And modified to use an IDE menu with fake descriptions:

asciicast

Tests

I only added a test for the style_suggestion helper that I added for highlighting the matched portions of a suggestion. Other than that, I just manually tried the menus out a bit. If there are any edge cases anyone can think of to test (either through unit tests or manually), I'd appreciate that.

I have a example for a columnar menu with fuzzy completions that you can copy into the examples/ folder and run for testing: https://gist.github.com/ysthakur/9cbb1fc1eec678eb2445ed7dff71fcdd.

After submitting

I plan to make a few more PRs:

  • One for making the fuzzy completer in Nushell take advantage of this match_indices field (Set match_indices for fuzzy-matched suggestions nushell#15887)
  • One for adding a display_value: Option<String> field to Suggestion (suggested by qfel here), giving Reedline consumers more control over what their users see
  • One for allowing custom/external completers in Nushell take advantage of display_value and match_indices

@ysthakur ysthakur marked this pull request as draft June 10, 2024 00:07
@ysthakur ysthakur marked this pull request as ready for review July 6, 2024 17:52
@ysthakur ysthakur marked this pull request as draft July 17, 2024 01:36
@ysthakur ysthakur marked this pull request as ready for review July 18, 2024 00:56
@sholderbach
Copy link
Member

I think @maxomatic458 would be the ideal reviewer here, based on recent work in the completion logic and the discussion we had around the pitfalls with this highlighting.

@maxomatic458
Copy link
Contributor

looks good so far.

I think instead of defaulting to this
https://github.com/ysthakur/reedline/blob/44e18841807ef914d302f57fc9cb9b2c151c099b/src/menu/ide_menu.rs#L516-L523

it might be better to just ignore the styling (so basically fully leave it up to the completer).

Then we could get rid of this trait function here (since we have the match_indices now):
https://github.com/ysthakur/reedline/blob/44e18841807ef914d302f57fc9cb9b2c151c099b/src/completion/base.rs#L39-L51

If you are ok with that i can make a PR for that.

@ysthakur
Copy link
Member Author

@maxomatic458 Interesting idea, I was going to say highlighting shouldn't be the completer's responsibility, but if it simplifies things, that'd be great. It's definitely worth a PR. @sholderbach Thoughts?

@ysthakur ysthakur marked this pull request as draft July 19, 2024 01:17
@qfel
Copy link

qfel commented Jul 19, 2024

I was going to say highlighting shouldn't be the completer's responsibility, but if it simplifies things, that'd be great.

How would that interact with other highlighting functionality in reedline? Eg. it takes care of highlighting the selected item, if the completer dealt with highlighting individual characters how would that mix?

it might be better to just ignore the styling (so basically fully leave it up to the completer).

Do you mean decoupling value from how it's displaying, eg. adding something like display_value to Suggestion, while value is still what gets put on the command line on selection?

Slightly tangential, but there's plenty of places that initialize Suggestion structs and have to deal with setting lots of fields to None (though mostly in nushell proper it seems) - maybe it's time to implement use Default?

@maxomatic458
Copy link
Contributor

Do you mean decoupling value from how it's displaying, eg. adding something like display_value to Suggestion, while value is still what gets put on the command line on selection?

I think this might actually be better solution. So instead of adding more stuff to the Suggestion we just have one display_value

that can be modified by a seperate styling layer (that can be attached to a completer).
This would also make styling way more customizable.

But this might require a good amount of breaking changes, so maybe thats something for a future PR?

@ysthakur
Copy link
Member Author

How would that interact with other highlighting functionality in reedline? Eg. it takes care of highlighting the selected item, if the completer dealt with highlighting individual characters how would that mix?

Ah, you're right @qfel, highlighting in the completer wouldn't work.

I think this might actually be better solution. So instead of adding more stuff to the Suggestion we just have one display_value

@maxomatic458 As @qfel pointed out, we'd need two display values, one in case the suggestion is selected and one in case it isn't, right? That feels like too much to me.

that can be modified by a seperate styling layer (that can be attached to a completer).
This would also make styling way more customizable.

@maxomatic458 This sounds interesting, could you explain more? (having a hard time figuring out what a separate styling layer would look like)

@maxomatic458
Copy link
Contributor

maxomatic458 commented Jul 20, 2024

@ysthakur

maybe this could be implemented as a trait
something like

pub trait SuggestionStyler {
    fn style_selected(&self, suggestion: Suggestion, ...) -> String {
        ...
    }
    
    fn style_unselected(&self, suggestion: Suggestion, ...) -> String {
        ...
    }
}

then we could pass a SuggestionStyler struct down to the menu and inside the create_string function of the menu we can style the suggestions

the functions of the SuggestionStyler trait could have paremeters like typed text, cursor pos

so we would move the styling out of the menu and out of the completer and we can implement it using this trait

Edit:
if we would add a display_value field to the suggestion we could just mutate it inside the trait functions,
so we would just need one field, and that would always be the string for whats currently being drawn (so not dependant on wether its selected or not)

@ysthakur
Copy link
Member Author

@maxomatic458 Sorry, still not getting it. Do you mean that the style field would be removed from Suggestion, the match_indices field from this PR would still be added, and then a SuggestionStyler would perform styling? And this styler could output by mutating a display_value field on the suggestion?

@maxomatic458
Copy link
Contributor

maxomatic458 commented Jul 24, 2024

@ysthakur
that approach would not need any more fields on the Suggestion itself
all styling would be handled inside this trait

that would potentially allow for more complex styling, without having to make any changes to the menu

so something like this here

enum MatchMode {
    Fuzzy,
    Prefix,
}

struct UnderlineStyler {
    color: ...,
    mode: MatchMode
}

impl SuggestionStyler for UnderlineStyler {
    fn style_selected(&mut self, suggestion: Suggestion, cursor_pos: Option<(u16, u16)>, text_typed_by_user: String, terminal_dims: Option<(u16, u16)>, ...) -> Suggestion {
        // Do the styling here
        ...
        return suggestion
    }
    
    fn style_unselected(...) -> Suggestion {
         ...
    }
}

then we could add this Styler as a field to the menus

and then call the trait functions in menu when we are generating the strings for the suggestions

Thats just an idea how it could be implemented if we want to make the suggestion-styling that extensible.
But i also understand that there probably isnt really a need to make it that extensible atm. But that would just avoid having to add more fields to the Suggestions struct in the future.

Im also ok with just adding the match_indices instead

@qfel
Copy link

qfel commented Jul 24, 2024

IIUC that would either mean we keep match_indices so that Styler can use the information to style part of the suggestion - in which case that seems fully orthogonal to this PR and better discuss outside (so we can make the smaller incremental change here).

Or it would mean inside the styler we have to recompute the matching indices, which sounds a bit unpleasant. Unless we allow to attach arbitrary data with suggestions - then completers could generate suggestions with completer-specific hints, and provide stylers that consume those hints to producer stylized output. Though that feels like a fairly big change?

@maxomatic458
Copy link
Contributor

maxomatic458 commented Jul 24, 2024

Or it would mean inside the styler we have to recompute the matching indices, which sounds a bit unpleasant

That was my idea (if you are concerned about the recomputing, i believe in both cases we would need to recompute the indices whenever the user types something). We would attach a Styler to a completer, and that would handle the styling of the suggestions.

so the Suggestions struct would not have to be modified again, when we want to introduce a new way of styling suggestions.

@ysthakur
Copy link
Member Author

@ysthakur
that approach would not need any more fields on the Suggestion itself
all styling would be handled inside this trait

@maxomatic458 Oh, I see now. I like the idea of avoiding adding fields to Suggestion to control styling, but as qfel said, recomputing the matching indices sounds unpleasant. Also, both the completer and the styler will need to be aware of how matching works.

That said, I agree with you that performance might not be a huge problem. Only a few suggestions are displayed on the screen at any point, even if there are hundreds of suggestions in total. If we only recompute the match indices for each suggestion when it shows up on the screen, the user may not see a noticeable delay.

I'm not an expert here, though. Anyone have any idea what impact this would have on performance?

so the Suggestions struct would not have to be modified again, when we want to introduce a new way of styling suggestions.

@maxomatic458 Did you have any possible future ways of styling suggestions in mind? Do you mean we might want to highlight suggestions in three different colors (rather than the current two)?

@maxomatic458
Copy link
Contributor

maxomatic458 commented Jul 25, 2024

@ysthakur

Also, both the completer and the styler will need to be aware of how matching works.

Ah now i see, yea in that case we would need to do the same calculation twice.

Did you have any possible future ways of styling suggestions in mind? Do you mean we might want to highlight suggestions in three different colors (rather than the current two)?

yes multicolored stuff would be possible.
Nushell currently has different colored file suggestions per filetype (i think you need to enable it in the config)
grafik

So if we provide file system information to the styler stuff like this would be possible.
We could even mutate the text of the suggestion (without changing the completion value if we add a display_value field)
so maybe we could add info like file size, or edit date or stuff like that to the suggestion.

like:

File 1 (1 GB) yesterday
File 2 (2 GB) 10 days ago

and because we can store data in the Styler struct, we could even cache stuff like this, so we dont need to fetch it every keystroke

@qfel
Copy link

qfel commented Jul 25, 2024

I agree with you that performance might not be a huge problem.

That aside, potentially having to run the same matching code in two different places in the Completer is an unpleasant API. Not a huge issue I suppose, but makes it a little harder to get things going (and might have some weird implications for non-deterministic/pure matching, maybe if somebody decided to do some server-side completions).

terminal_dims: Option<(u16, u16)>

I noticed one of the examples above had this - what would it be used for?

Hm let me expand a bit on the styler idea that I think could work well (if we really want to go there):

  1. We split Suggestion into two separate types, so to not mix presentation with completion (plus for some fields it would make no sense to change them in Styler, so why have it push them trough):
pub struct Suggestion<T> {
    /// String replacement that will be introduced to the the buffer
    pub value: String,
    /// Replacement span in the buffer
    pub span: Span,
    /// Whether to append a space after selecting this suggestion.
    /// This helps to avoid that a completer repeats the complete suggestion.
    pub append_whitespace: bool,
    /// Completer-associated context, passed back to Styler.
    pub context: T,
}

pub struct DisplaySuggestion {
    /// The value to display, often the same as coming from Suggestion but will have ANSI escapes.
    pub value: String,
    /// Optional description for the replacement, can contain ANSI escapes.
    pub description: Option<String>,
    /// Optional vector of strings in the suggestion. These can be used to
    /// represent examples coming from a suggestion. Can contain ANSI escapes.
    pub extra: Option<Vec<String>>,
}
  1. We introduce a Styler trait, to convert Suggestion to DisplaySuggestion:
// Probably needs more thought about the naming.
pub trait Styler<T> {
  fn display(&self, suggestion: Suggestion<T>, is_selected: bool, some_type_of_user_config: _, ...) -> DisplaySuggestion;
  // Also batch_display with some default implementation. May be useful for some completers to parallelize.
}
  1. Update Completer to allow for generic Suggestions and Styler.
pub trait Completer {
  type Context;
  fn complete(&mut self, line: &str, pos: usize) -> Vec<Suggestion<Self::Context>>;

  // We *probably* want to instead have it be a separate field on ReedlineMenu::WithCompleter,
  // so that any compatible Styler can be used. But that's maybe something to think on later.
  //
  // This could return one of predefined simple static stylers, or something custom for the completer.
  fn styler<'a>(&'a self) -> &'a dyn Styler<Self::Context>;
}
  1. Provide some basic Stylers, eg. one for highlighting the entire item, one highlighting a prefix (for completers with eg. u32 Context). New Stylers could use the base ones for generating regular DisplaySuggestion and then updating just a few fields as needed.

Regarding the Context associated type: it don't necessarily think it's important for performance (though that really depends on a particular completer), but aside from making think a bit (I think) cleaner, it also can serve as a way to declare which Stylers are compatible with which Completers - which in turn would let use decouple the two more, rather than have Completer define a single associated Styler.

@maxomatic458
Copy link
Contributor

terminal_dims: Option<(u16, u16)>

I noticed one of the examples above had this - what would it be used for?

Yea not really sure what that could be used for either, just came into my mind when thinking of things that might be useful to style a suggestion.

I think it would also be useful to store the string the completer used to suggest that suggestion in the Suggestion struct.

fdncred pushed a commit to nushell/nushell that referenced this pull request Jul 30, 2024
# Description

Take advantage of the `Default` implementation of `Suggestion`. This in
particular should make code compatible forward-compatible with
nushell/reedline#798.

# User-Facing Changes
None

# Tests + Formatting

Existing coverage.
@ysthakur
Copy link
Member Author

I think it would also be useful to store the string the completer used to suggest that suggestion in the Suggestion struct.

@maxomatic458 Would this be used by the Styler trait to have more information for styling?

Not a huge issue I suppose, but makes it a little harder to get things going (and might have some weird implications for non-deterministic/pure matching, maybe if somebody decided to do some server-side completions).

That's a good point, @qfel, running matching twice wouldn't be good for non-deterministic/time-consuming suggestions.

That said, match_indices won't be enough if we ever decide we want more than 2 styles in a single suggestion, e.g. green for the first half, red for the second half, underlines for the matched characters. I personally cannot think of why this would happen, but it is possible we need advanced styling in the future.

@maxomatic458's display_value idea solves that, but I was thinking that instead of a single field, we could instead have two fields, display_value_unselected and display_value_selected. Instead of providing a style, each completer could style its suggestions completely on its own, using helper functions provided by Reedline. The advanced styling that would have gone into the Styler trait would be done by each completer instead, though most would just Reedline's helpers for that. No match_indices field would be needed in each suggestion itself. Thoughts?

@maxomatic458
Copy link
Contributor

Would this be used by the Styler trait to have more information for styling?

@ysthakur that could be also be used outside of styling. Currently we have the helper function "complete_with_base_ranges", that basically does the same thing already, but instead of collecting the actual strings, we just get the ranges in the buffer (i think).

So an extra field that holds the "completion base value" could be used to store that instead.
Currently thats required to align the IDE menu suggestions with the text already typed in the terminal.

/// If true, the cursor pos will be corrected, so the suggestions match up with the typed text
/// ```text
/// C:\> str
/// str join
/// str trim
/// str split
/// ```
pub correct_cursor_pos: bool,

@webbdays
Copy link

webbdays commented Mar 29, 2025

Hi,
does this also solves the issue of
mismatch in highlight.
the create_string is assuming the match string start at the front.

Thanks.
Kunam Balaram Reddy

@webbdays
Copy link

webbdays commented Mar 29, 2025

updating create_string method is enough i think.
split suggestion.value into three parts and add highlight to matched part and return a formatted string.

like this

let suggestion_style_prefix = suggestion.clone()
        .style
        .unwrap_or(Style::new().bold().fg(Color::Cyan))
        .prefix();
let extras = suggestion.extra.as_ref().unwrap();
let match_str = extras.get(0).unwrap();
let splits = Self::split_string_by_pattern(&suggestion.value, &match_str).unwrap();

format!(
    "{}{}{}{}{}{}{}{}{}{:>empty$}{}{}",
    suggestion_style_prefix,
    splits.0,
    Style::default().underline().prefix(),
    match_str,
    RESET,
    suggestion_style_prefix,
    splits.2,
    RESET,
    Color::Yellow.normal().prefix(),
    "",
    RESET,
    "\r\n",
    empty = empty_space,
)

for example.

@divanshu-go
Copy link
Contributor

divanshu-go commented Apr 26, 2025

@ysthakur The regex dependency remains in Cargo.lock because it's a transitive dependency of rstest (our test framework)

@ysthakur ysthakur marked this pull request as ready for review May 16, 2025 04:29
@ysthakur
Copy link
Member Author

ysthakur commented May 16, 2025

This PR now does the ANSI sequence parsing itself, rather than using regex. It should be ready to merge now (built and ran Nushell with these changes and things seem fine). Scratch that, need to merge nushell/nushell#15764 first so that the new field added to Suggestion won't cause problems (edit: merged).

WindSoilder pushed a commit to nushell/nushell that referenced this pull request May 16, 2025
# Description

In preparation for nushell/reedline#798, which
adds a new field to `Suggestion`, this PR makes sure that `Suggestion`s
are created using `..Default::default()` inside
`attribute_completions.rs`.

# User-Facing Changes

None

# Tests + Formatting

None

# After Submitting
@ysthakur ysthakur added the A-Completions Area: Tab completion and inline hint completions label Jun 4, 2025
ysthakur and others added 3 commits October 16, 2025 22:34
Make columnar_menu use match indices

Make ide menu use match indices

Add fuzzy completions example

Test style_suggestion

Make doctests in default.rs pass

Highlight entire graphemes

Extract ANSI escapes from strings to apply match highlighting

Fix clippy lint for fuzzy completion example

Shut the typo checker up

Use existing variable `escape`

Copy regex from parse-ansi crate
Fix padding for columnar menu

Highlight substring matches too by default

Simplify (?) columnar menu
@ysthakur ysthakur force-pushed the fuzzy-select-underline branch from c2dc5fc to e18f52a Compare October 17, 2025 02:35
@ysthakur ysthakur marked this pull request as draft October 20, 2025 05:38
@ysthakur ysthakur self-assigned this Oct 20, 2025
@ysthakur ysthakur marked this pull request as ready for review October 21, 2025 10:41
@ysthakur
Copy link
Member Author

I think this is ready to be merged! @maxomatic458 could you look over it to make sure it looks alright?

@ysthakur ysthakur requested review from 132ikl and kubouch October 21, 2025 11:07
Copy link
Contributor

@kubouch kubouch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have anything against merging it

@ysthakur ysthakur merged commit 40c562c into nushell:main Oct 22, 2025
6 checks passed
sholderbach pushed a commit to nushell/nushell that referenced this pull request Oct 22, 2025
Use the latest commit of Reedline on the `main` branch so we can use
[#798](nushell/reedline#798) (Add match_indices
field to Suggestion)

<!--
Thank you for improving Nushell!
Please, read our contributing guide:
https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md
-->

## Release notes summary - What our users need to know
<!--
This section will be included as part of our release notes. See the
contributing guide for more details.
Please include only details relevant for users here. Motivation and
technical details can be added above or below this section.

You may leave this section blank until your PR is finalized. Ask a core
team member if you need help filling this section.
-->

N/A

## Tasks after submitting
<!-- Remove any tasks which aren't relevant for your PR, or add your own
-->
- [ ] Make use of the new Suggestion field in
#15887
benvansleen added a commit to benvansleen/reedline that referenced this pull request Oct 26, 2025
* fix: prompt glitch when resizing with cursor in a multiline command (nushell#898)

* fix: prompt glitch when resizing with cursor in a multiline command

* fix: considering line wraps

* fix: clippy

* Bump version to `0.41.0` (nushell#936)

* Protect against invalid suggestion spans (nushell#915)

* Protect against invalid suggestion spans

* Protect against start > end

* feat: Builder option to immediately accept input (nushell#933)

* feat: Option to immediately accept input

* chore: PR feedback

* feat: add `ViChangeMode` event (nushell#932)

* feat: add `ViChangeMode` event

* fix: use `FromStr` trait

* fix: undo unused change

* fix: clippy

* Fix `mismatched_lifetime_syntaxes` (nushell#947)

From Rust 1.89.0 on this lints.
https://blog.rust-lang.org/2025/08/07/Rust-1.89.0/#mismatched-lifetime-syntaxes-lint

* Fix missing import in README.md (nushell#942)

Co-authored-by: sholderbach <[email protected]>

* fix: dislocation of cursor after previous_history navigation to a multiline entry (nushell#899)

* bumping version to 42 (nushell#949)

Co-authored-by: Jack Wright <[email protected]>

* Bump `rusqlite` to 0.37 (nushell#950)

* feat: make columnar menu traversal direction configurable (nushell#951)

* Make columnar menu traversal direction configurable

* Add tests for columnar menu selection position updates

* Apply changes based on review

* Upgrade GitHub Actions and Rust toolchain versions (nushell#954)

* Upgrade GitHub Actions and Rust toolchain versions

* Update .github/workflows/ci.yml

* Vi mode text objects for word, WORD, brackets and quotes (nushell#939)

* Addd initial change inner and around word text objects and handle whitespace

Note a buffer full of whitespace is not properly considered and still
causing incorrect behaviour. TODO fix this.

* Renaming functions and fix default value of current_whitespace_range_start

* Rename cut/yank inside enums and methods to cut/yank inside pair and add general yank/cut range methods

* Use TextObject enum instead of passing through the character

* WIP: Add quote and bracket text objects and add jumping if not inside objects

* Add my own methods for finding matching pair and jumping

* Fix bugs in new function to get matching pair range and it's finish features

- Now handles jumps to next open/close or equal symbol pairs if not in a
pair already
- Searching only on current line for equal symbol pairs e.g. quotes
- Correctly handles graphemes

* Simplify heirarchy of pair range finding functions

- Refactor the structure of the methods to get ranges, don't need to
pass in depth unecessarily, high level functions don't require cursor
passed in.
- Now two seperate functions for ranges, one "next" and one "current"
range that gets you either the range inside next text object or inside
current one depending on position of cursor.
- Finilise logic to correctly handle graphemes (not byte sized chars)

TODO Update unit tests

* Refactoring range functions and tidy up/extend unit test cases and coverage

* More refactoring

- Improve some text object ranges to use iterators rather than complex
logic
- Clean up documentation, add consts etc
- Look through and refactor some editor functions

* Move text object range methods into line_buffer from editor

* Combine line_buffer quote and pair text object functions into generic and rewrite a lot of doc strings

* Testing for quote and bracket text object functions in editor.rs

* Whitespace

* Rework unit tests for new function structure

* Remove angle brackets from b text object

* Rename yank text object functions to copy

* Add bracket test cases to range_inside_next_pair_in_group unit tests

* Add more detailed unicode safety tests

* Fix display enum string for renamed enums

* Unicode and overflow/underflow safety when expanding text object ranges

* Pass through matching pair group const for quote and bracket text object functions

* Rename yank_range -> copy_range for consistency with other methods

* Remove unecessary guard clause from expand_range_to_include_pair

* Correct display string for CutInsidePair

* Make text object types public (nushell#957)

* Make TextObject, TextObjectScope and TextObjectType public

* Correct CopyInsidePair and CopyAroundPair EditType to NoOp

* fix: dislocation of cursor during history navigation (nushell#959)

* fix: dislocation of cursor during history navigation

* test: new test case by Claude Sonnet

* simplify

* Fix typos (nushell#962)

* Bump version for `0.43.0` release (nushell#961)

* Fix shift selection in vi (insert) & emacs mode (nushell#927)

* Add match_indices field to Suggestion (nushell#798)

* Add match_indices field to Suggestion

Make columnar_menu use match indices

Make ide menu use match indices

Add fuzzy completions example

Test style_suggestion

Make doctests in default.rs pass

Highlight entire graphemes

Extract ANSI escapes from strings to apply match highlighting

Fix clippy lint for fuzzy completion example

Shut the typo checker up

Use existing variable `escape`

Copy regex from parse-ansi crate

* replace LazyLock with lazy_static that works with Rust 1.63.0 (#2)

* Homegrown ANSI parser

Fix padding for columnar menu

Highlight substring matches too by default

Simplify (?) columnar menu

* Fix clippy lints after rebase

* Use get_match_indices helper

* Stop using 'fo' because it's a typo? Fo shizzle.

* Use to_string() instead of as_str()

* Style entire suggestion same color

* RESET after suggestion

---------

Co-authored-by: Divanshu Grover <[email protected]>

* fix bashism parsing (nushell#958)

* refactor: use crossterm `supports_keyboard_enhancement` once when KittyProtocolGuard is initialized (nushell#920)

Co-authored-by: Pierre POLLET <[email protected]>

---------

Co-authored-by: zc he <[email protected]>
Co-authored-by: Stefan Holderbach <[email protected]>
Co-authored-by: Yash Thakur <[email protected]>
Co-authored-by: Stuart Carnie <[email protected]>
Co-authored-by: Daniel Bonofiglio <[email protected]>
Co-authored-by: Daniel del Castillo <[email protected]>
Co-authored-by: Jack Wright <[email protected]>
Co-authored-by: Jack Wright <[email protected]>
Co-authored-by: Piepmatz <[email protected]>
Co-authored-by: simonborje <[email protected]>
Co-authored-by: Darren Schroeder <[email protected]>
Co-authored-by: JonLD <[email protected]>
Co-authored-by: Collin Murch <[email protected]>
Co-authored-by: Divanshu Grover <[email protected]>
Co-authored-by: migraine-user <[email protected]>
Co-authored-by: PtiBouchon <[email protected]>
Co-authored-by: Pierre POLLET <[email protected]>
ysthakur added a commit to nushell/nushell that referenced this pull request Nov 9, 2025
# Description

Requires nushell/reedline#798, which adds a
`match_indices` field to `Suggestion` that allows completers to specify
exactly which graphemes in the suggestion matched the typed text. This
PR takes advantage of this field to accurately underline fuzzily-matched
suggestions.

<img width="890" height="311" alt="image"
src="https://github.com/user-attachments/assets/74443a82-1fe8-4a92-8679-41e28b871017"
/>

Note that file/directory/dotnu completions don't currently make use of
the `match_indices` field. Once we have a way to have separate display
values, this will be much easier to implement.

# User-Facing Changes

Users will see sensible highlighting for suggestions when using fuzzy
matching, nothing else.

# Tests + Formatting

Just manually triggered completions to make sure things look okay.

# After Submitting

No need to update docs for this.

---------

Co-authored-by: blindfs <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Completions Area: Tab completion and inline hint completions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants